package com.zb.config;

import cn.dev33.satoken.exception.NotLoginException;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.zb.exception.*;
import com.zb.result.Result;
import com.zb.result.ResultCode;
import com.zb.utils.RequestUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.tomcat.util.http.fileupload.impl.SizeException;
import org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 全局异常处理类
 * @Author WEN
 * @Date 2023/7/18 0018
 **/
@Log4j2
@ResponseBody
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 微信异常
     * @param e
     * @return
     */
    @ExceptionHandler(WxException.class)
    public Result WxException(WxException e) {
        e.printStackTrace();
        return Result.error(ResultCode.THIRD_WX.getCode(), e.getMessage());
    }


    /**
     * mybatis-plus 校验异常
     * @param e
     * @return
     */
    @ExceptionHandler(MybatisPlusException.class)
    public Result mybatisPlusException(MybatisPlusException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，非法参数异常：{}", request.getRequestURI(), e);
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), e.getMessage());
    }

    /**
     * 非法参数异常
     * @param e
     * @return
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public Result IllegalArgumentException(IllegalArgumentException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，非法参数异常：{}", request.getRequestURI(), e);
        if (e.getMessage().startsWith("http://") || e.getMessage().startsWith("https://")) {
            return Result.error(ResultCode.OBJECT_PARAM.getCode(), "请检查传入的域名是否有误：" + e.getMessage());
        }
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "输入的参数不符合规定，请检查输入的参数是否有误！");
    }

    /**
     * 参数内容值重复异常
     * @param e
     * @return
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public Result DuplicateKeyException(DuplicateKeyException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，参数内容值重复异常：{}", request.getRequestURI(), e);
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "输入的参数内容重复");
    }

    /**
     * 参数内容超长异常
     * @param e
     * @return
     */
    @ExceptionHandler(DataIntegrityViolationException.class)
    public Result DataIntegrityViolationException(DataIntegrityViolationException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，非法参数异常：{}", request.getRequestURI(), e);
        if (e.getCause().getMessage().contains("doesn't have a default value")) {
            return Result.error(ResultCode.OBJECT_PARAM.getCode(), "必填字段内容不能为空");
        }
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "字段内容长度超限");
    }

    /**
     * 参数字段校验类异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidException(MethodArgumentNotValidException e) {
        e.printStackTrace();
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), Objects.requireNonNull(e.getFieldError()).getDefaultMessage());
    }

    /**
     * 百度应用接口异常
     * @param e
     * @return
     */
    @ExceptionHandler(BaiduAppException.class)
    public Result baiduAppException(BaiduAppException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}", request.getRequestURI());
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "百度应用接口提示：" + e.getMessage());
    }

    /**
     * @param e
     * @return
     */
    @ExceptionHandler({ZbException.class})
    public Result zbException(ZbException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，非法参数异常：{}", request.getRequestURI(), e);
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "输入的参数不合规，请检查输入的参数是否有误！");
    }



    /**
     * 接口请求类的异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result HttpMessageNotReadableException(HttpMessageNotReadableException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，接口请求类的异常：{}", request.getRequestURI(), e);
        if (null != e.getCause()) {
            return Result.error(ResultCode.HTTP_STATUS.getCode(), "发送请求出错，请检查发送的请求或相关参数是否有误");
        }
        return Result.error(ResultCode.HTTP_STATUS.getCode(), "发送请求出错，请检查发送的请求或相关参数是否有误");
    }

    /**
     * 短信类异常
     * @param e
     * @return
     */
    @ExceptionHandler(SMSException.class)
    public Result SMSException(SMSException e) {
        e.printStackTrace();
        return Result.error(ResultCode.SMS.getCode(), e.getMessage());
    }


    /**
     * 登录类异常
     * @param e
     * @return
     */
    @ExceptionHandler(LoginException.class)
    public Result loginException(LoginException e) {
        e.printStackTrace();
        return Result.error(ResultCode.LOGIN_FAIL.getCode(), e.getMessage());
    }

    /**
     * 登录类异常
     * @param e
     * @return
     */
    @ExceptionHandler(NotLoginException.class)
    public Result NotLoginException(NotLoginException e) {
        e.printStackTrace();
        return Result.error(ResultCode.LOGIN_EXPIRE.getCode(), ResultCode.LOGIN_EXPIRE.getMessage());
    }

    /**
     * 文件上传异常
     * @param e
     * @return
     */
    @ExceptionHandler(MultipartException.class)
    public Result multipartException(MultipartException e) {
        e.printStackTrace();
        SizeException sizeCause = (SizeLimitExceededException) e.getCause().getCause();
        if (null != sizeCause) {
            return Result.error(ResultCode.FILE.getCode(), "文件上传超出限制，允许上传文件大小：<="+ (sizeCause.getPermittedSize() /1024/1024) +"M，实际上传文件大小："+ (long)(sizeCause.getActualSize()/1024/1024) + "M");
        }
        return Result.error(ResultCode.FILE.getCode(), "文件上传错误！");
    }

    /**
     * 商家认证标识异常
     * @param e
     * @return
     */
    @ExceptionHandler(VendorIdentifierException.class)
    public Result vendorIdentifierException(VendorIdentifierException e) {
        e.printStackTrace();
        return Result.error(ResultCode.VENDOR_IDENTIFIER.getCode(), e.getMessage());
    }

    /**
     * 方法参数类型不匹配异常
     * @param e
     * @return
     */
    @ExceptionHandler(TypeMismatchException.class)
    public Result methodArgumentTypeMismatchException(TypeMismatchException  e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，方法参数类型不匹配异常：{}", request.getRequestURI(), e);
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "请求参数类型不匹配，请检查参数是否正确");
    }

    /**
     * 方法参数类型异常
     * @param e
     * @return
     */
    @ExceptionHandler(NumberFormatException.class)
    public Result NumberFormatException(NumberFormatException e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，方法参数类型异常：{}", request.getRequestURI(), e);
        return Result.error(ResultCode.OBJECT_PARAM.getCode(), "整数类型参数转换失败，请检查参数是否正确");
    }


    /**
     * 请求方式异常
     * @param e
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result HttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{} 异常信息：{}", request.getRequestURI(), e);
        e.printStackTrace();
        return Result.error(ResultCode.HTTP_METHOD_CDE.getCode(), "请求方式错误，请检查您的请求方式");
    }

    /**
     * 无打款权限异常
     * */
    @ExceptionHandler(NoAuthPayException.class)
    public Result noAuthPayException(NoAuthPayException e) {
        e.printStackTrace();
        return Result.error(50000, e.getMessage());
    }

    /**
     * 未知异常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public Result unknownException(Exception e) {
        e.printStackTrace();
        HttpServletRequest request = RequestUtil.getRequestByContext();
        log.error("异常路径：{}，未知异常：{}", request.getRequestURI(), e);
        return Result.error(ResultCode.UNKNOWN.getCode(), ResultCode.UNKNOWN.getMessage());
    }
}
